package cn.openea.perpartner.sysuser.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.openea.perpartner.common.core.constant.Constants;
import cn.openea.perpartner.common.core.constant.UserConstants;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.manager.AsyncManager;
import cn.openea.perpartner.common.core.utils.MessageUtils;
import cn.openea.perpartner.common.core.web.domain.AjaxResult;
import cn.openea.perpartner.common.log.factory.AsyncFactory;
import cn.openea.perpartner.system.entity.SysUser;
import cn.openea.perpartner.system.entity.SysUserUnion;
import cn.openea.perpartner.system.entity.dto.UserInfoDto;
import cn.openea.perpartner.system.enums.AppletsEnums;
import cn.openea.perpartner.system.service.ISysConfigService;
import cn.openea.perpartner.system.service.ISysUserService;
import cn.openea.perpartner.system.service.ISysUserUnionService;
import cn.openea.perpartner.system.util.ToolsUtil;
import cn.openea.perpartner.sysuser.domain.LoginBody;
import cn.openea.perpartner.sysuser.domain.UserDto;
import cn.openea.perpartner.sysuser.service.IAppletsService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author Weird077
 * @description TODO
 * @date 2022-04-28 10:19
 */
@Slf4j
@Service
public class AppletsServiceImpl implements IAppletsService {
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private ISysUserUnionService unionService;
    @Autowired
    private ScheduledService scheduledService;

    @Override
    public JSONObject login(LoginBody loginBody) {
        SysUser user = new SysUser();
        //获取微信
        String loginStatus = loginBody.getStatus();
        JSONObject wxObject = new JSONObject();
        //小程序openid
        String openid;
        //平台联合id
        String unionid;
        String appletId = loginBody.getAppletId();
        AppletsEnums applet = AppletsEnums.getApplet(appletId);
        if (StrUtil.isBlank(loginStatus)) {
            wxObject = getWxObject(loginBody.getCode(), applet);
            openid = wxObject.getString("openid");
            unionid = wxObject.getString("unionid");
        } else {
            openid = loginBody.getOpenId();
            unionid = loginBody.getUnionId();
        }
        if (StrUtil.isBlank(openid)) {
            throw new ServiceException("openid为空，登录失败!");
        }
        if (StrUtil.isBlank(unionid)) {
            throw new ServiceException("unionid为空，登录失败!");
        }
        String sessionKey = wxObject.getString("session_key");
        boolean isNewUser = false;
        //校验是否生成平台账号
        String userId = loginBody.getUserId();
        if (UserConstants.UNIQUE.equals(userService.checkUserUnique(unionid))) {
            isNewUser = true;
            userId = StrUtil.isBlank(userId) ? ToolsUtil.autoUserID() : userId;
            user.setUserid(userId);
            user.setNickname(loginBody.getNickName());
            user.setAvatar(loginBody.getAvatarUrl());
            user.setUnionid(unionid);
            user.setPassword(BCrypt.hashpw("openeapass", BCrypt.gensalt()));
            user.setStepstatus("1");
            user.setIsSubscribed("0");
            user.setAppid(applet.getAppId());
            userService.saveOrUpdate(user);
            user.setAppletId(appletId);
            userService.updateUserCache(user);
        }
        //获取用户信息
        user = userService.findUser(unionid);
        userId = user.getUserid();
        //校验小程序是否注册
        SysUserUnion union = new SysUserUnion();
        if (UserConstants.UNIQUE.equals(unionService.checkUserUnique(openid, unionid))) {
            isNewUser = true;
            union.setOpenid(openid);
            union.setUnionid(unionid);
            union.setUserid(userId);
            union.setMyopenid(user.getMyopenid());
            union.setAppid(applet.getAppId());
            unionService.saveOrUpdate(union);
        } else {
            union = unionService.selectByOpenId(openid, unionid);
            if (StrUtil.isBlank(union.getMyopenid())) {
                union.setMyopenid(user.getMyopenid());
                union.setAppid(applet.getAppId());
                unionService.saveOrUpdate(union);
            }
        }
        //更新用户头像和昵称
        if (StrUtil.isNotBlank(loginStatus)) {
            user.setNickname(loginBody.getNickName());
            user.setAvatar(loginBody.getAvatarUrl());
            user.setAppid(applet.getAppId());
            userService.saveOrUpdate(user);
            user.setAppletId(loginBody.getAppletId());
            userService.updateUserCache(user);
        }
        //注册、登录记录
        AsyncManager.me().execute(AsyncFactory.recordLoginInfo(user.getUserid(), Constants.REGISTER,
                MessageUtils.message(isNewUser ? "user.register.success" : "user.login.success")));
        //同步用户到bpm
        String url = configService.selectConfigByKey(appletId + ".account.async.url");
        if (StrUtil.isNotBlank(url) && StrUtil.isNotBlank(loginStatus)) {
            wxObject.put("openid", openid);
            wxObject.put("subscriptionOpenid", user.getMyopenid());
            wxObject.put("stepStatus", user.getStepstatus());
            wxObject.put("isSubscribed", user.getIsSubscribed());
            BeanUtil.copyProperties(user, wxObject, false);
            AsyncManager.me().execute(AsyncFactory.asyncBpmOrg(url, wxObject));
        }
        return buildResponse(user, openid, unionid, sessionKey, isNewUser);
    }

    @Override
    public JSONObject thirdPartyLogin(LoginBody loginBody) {
        //获取微信
        String loginStatus = loginBody.getStatus();
        String appletId = loginBody.getAppletId();
        AppletsEnums applet = AppletsEnums.getApplet(appletId);
        JSONObject wxObject = new JSONObject();
        //小程序openid
        String openid = "";
        String unionid = "";
        if (StrUtil.isBlank(loginStatus)) {
            wxObject = getWxObject(loginBody.getCode(), applet);
            openid = wxObject.getString("openid");
            unionid = wxObject.getString("unionid");
        } else {
            openid = loginBody.getOpenId();
        }
        if (StrUtil.isBlank(openid)) {
            throw new ServiceException("openid为空，登录失败!");
        }
        String sessionKey = wxObject.getString("session_key");
        boolean isNewUser = false;
        String userId = loginBody.getUserId();
        //校验小程序是否注册
        SysUserUnion union = new SysUserUnion();
        //unionid为空的情况
        if (StrUtil.isBlank(unionid) && UserConstants.UNIQUE.equals(unionService.checkUserUniqueByOpenId(openid))) {
            isNewUser = true;
            userId = StrUtil.isBlank(userId) ? ToolsUtil.autoUserID() : userId;
            union.setOpenid(openid);
            union.setUserid(userId);
            union.setAppid(applet.getAppId());
            unionService.saveOrUpdate(union);
            //unionid不为空的情况
        } else if (StrUtil.isNotBlank(unionid) && UserConstants.UNIQUE.equals(unionService.checkUserUnique(openid, unionid))) {
            isNewUser = true;
            userId = StrUtil.isBlank(userId) ? ToolsUtil.autoUserID() : userId;
            union.setOpenid(openid);
            union.setUserid(userId);
            union.setUnionid(unionid);
            union.setAppid(applet.getAppId());
            unionService.saveOrUpdate(union);
        } else {
            union = unionService.selectByOpenId(openid);
            userId = union.getUserid();
        }
        SysUser user = new SysUser();
        //校验是否生成平台账号
        if (UserConstants.UNIQUE.equals(userService.checkUserUnique(userId))) {
            isNewUser = true;
            user.setUserid(userId);
            user.setUnionid(unionid);
            user.setNickname(loginBody.getNickName());
            user.setAvatar(loginBody.getAvatarUrl());
            user.setPassword(BCrypt.hashpw("openeapass", BCrypt.gensalt()));
            user.setStepstatus("1");
            user.setIsSubscribed("0");
            user.setAppid(applet.getAppId());
            userService.saveOrUpdate(user);
            user.setAppletId(appletId);
            userService.updateUserCache(user);
        } else {
            //获取用户信息
            user = userService.findUser(userId);
        }
        //更新用户头像和昵称
        if (StrUtil.isNotBlank(loginStatus)) {
            user.setNickname(loginBody.getNickName());
            user.setAvatar(loginBody.getAvatarUrl());
            user.setAppid(applet.getAppId());
            userService.saveOrUpdate(user);
            user.setAppletId(loginBody.getAppletId());
            userService.updateUserCache(user);
        }
        //注册、登录记录
        AsyncManager.me().execute(AsyncFactory.recordLoginInfo(user.getUserid(), Constants.REGISTER,
                MessageUtils.message(isNewUser ? "user.register.success" : "user.login.success")));
        return buildResponse(user, openid, unionid, sessionKey, isNewUser);
    }


    private JSONObject getWxObject(String code, AppletsEnums applet) {
        return ToolsUtil.getData(code, applet.getAppId(), applet.getSecret());
    }

    @Override
    public JSONObject saveUserInfo(UserDto dto) {
        SysUser user = userService.findUser(dto.getUserId());
        if (BeanUtil.isNotEmpty(user)) {
            user.setPhonenumber(dto.getPhoneNumber());
            userService.saveOrUpdate(user);
            user.setAppletId(dto.getAppletId());
            userService.updateUserCache(user);
        }
        String result = "{\"status\":\"500\",\"msg\":\"err\"}";
        String url = configService.selectConfigByKey(dto.getAppletId() + ".account.async.url");
        if (StrUtil.isNotBlank(url)) {
            Map<String, Object> formMap = new HashMap<>();
            formMap.put("appid", "perpartner");
            formMap.put("wf_num", "R_perpartner_BW010");
            formMap.putAll(BeanUtil.beanToMap(dto));
            HttpResponse res = HttpRequest.post(url)
                    .header("sysid", "SysAdmin")
                    .header("syspwd", "pass")
                    .header("userId", "admin")
                    .form(formMap)
                    .execute();
            result = res.body();
        }
        return JSON.parseObject(result);
    }

    @Override
    public boolean singleSync(String userId, String appId) {
        if (StrUtil.isBlank(userId) || StrUtil.isBlank(appId)) {
            return false;
        }
        UserInfoDto dto = userService.selectByUserId(userId, appId);
        if (BeanUtil.isEmpty(dto)) {
            return false;
        }
        String url = configService.selectConfigByKey(appId + ".account.async.url");
        if (StrUtil.isNotBlank(url)) {
            Map<String, Object> formMap = new HashMap<>();
            formMap.put("formData", BeanUtil.toBean(dto, JSONObject.class));
            formMap.put("appid", "perpartner");
            formMap.put("wf_num", "R_perpartner_BW005");
            HttpResponse res = HttpRequest.post(url)
                    .header("sysid", "SysAdmin")
                    .header("syspwd", "pass")
                    .header("userId", "admin")
                    .form(formMap)
                    .execute();
            return res.isOk();
        }
        return false;
    }

    @Override
    public boolean batchAsync() {
        return scheduledService.scheduled();
    }

    @Override
    public AjaxResult createUser(SysUser user) {
        String userId = ToolsUtil.autoUserID();
        user.setUserid(userId);
        boolean result = userService.save(user);
        if (result) {
            return AjaxResult.success().put("userId", userId);
        }
        return AjaxResult.error();
    }

    @Override
    public AjaxResult deleteUsers(List<String> idList) {
        if (CollUtil.isEmpty(idList)) {
            return AjaxResult.error("请选择要删除的用户");
        }
        boolean result = userService.removeBatchByUserIds(idList);
        return result ? AjaxResult.success() : AjaxResult.error();
    }

    private JSONObject buildResponse(SysUser user, String openid, String unionid, String sessionKey, boolean isNewUser) {
        JSONObject object = new JSONObject();
        object.put("status", "1");
        object.put("isNewUser", isNewUser);
        object.put("msg", "openea");
        JSONObject data = new JSONObject();
        data.put("avatarUrl", user.getAvatar());
        data.put("openid", openid);
        data.put("unionid", unionid);
        data.put("session_key", sessionKey);
        data.put("userId", BeanUtil.isNotEmpty(user) ? user.getUserid() : "");
        data.put("nickName", user.getNickname());
        data.put("phoneNumber", BeanUtil.isNotEmpty(user) ? user.getPhonenumber() : "");
        object.put("data", data);
        return object;
    }
}
